Inside Macintosh: Sound

| Previous | Chapter contents | Chapter top | Section top | Next |

Finding and Changing Component Capabilities

All sound components take a stream of input data and produce a (usually different) stream of output data. The Sound Manager needs to know what operations your component can perform, so that it knows what other sound components might need to be linked together to play a particular sound on the available sound output device. It calls your component's SoundComponentGetInfo and SoundComponentSetInfo functions to get and set information about the capabilities and current settings of your sound component.

To specify the kind of information it wants to get or set, the Sound Manager passes your component a sound component information selector. If your component does not support a particular selector, if should pass the selector to the specified sound source. If your component does support the selector, it should either return the desired information directly or alter its settings as requested.

The sound component information selectors can specify any of a large number of audio capabilities or component settings. For example, the selector siRateMultiplier is passed to get or set the current output sample rate multiplier value.

The Sound Manager uses many of the sound input device information selectors defined by the Sound Input Manager for communicating with sound input devices. See "Sound Input Manager" in this book for a description of the sound input device information selectors. A complete list of all sound component information selectors is provided in "Sound Component Information Selectors" .

Your component's SoundComponentGetInfo function has the following declaration:

pascal ComponentResult SoundComponentGetInfo (ComponentInstance ti,
                                                    SoundSource sourceID, OSType selector,
                                                    void *infoPtr);

The sound component information selector is passed in the selector parameter. The sound source is identified by the source ID passed in the sourceID parameter. The  infoPtr parameter specifies the location in memory of the information returned by  SoundComponentGetInfo . If the information to be returned occupies four bytes or fewer, you can simply return the information in the location pointed to by that parameter. Otherwise, you should pass back in the infoPtr parameter a pointer to a record of type SoundInfoList , which contains an integer and a handle to an array of data items. In the second case, you'll need to allocate memory to hold the information you need to pass back. Listing 8 defines a component's SoundComponentGetInfo routine. It returns information to the Sound Manager about its capabilities and current settings.

Listing 8 Getting sound component information

static pascal ComponentResult MySoundComponentGetInfo
                            (SoundComponentGlobalsPtr globals, SoundSource sourceID,
                                OSType selector, void *infoPtr)
{
    HandleListPtr               listPtr;
    short                       *sp, i;
    UnsignedFixed               *lp;
    Handle                      h;
    HardwareGlobalsPtr          hwGlobals = globals->hwGlobals;
    ComponentResult             result = noErr;

    /*Make sure we got our global variables.*/
    if (hwGlobals == nil)
        return (notEnoughHardwareErr);

    switch (selector)
    {
        case siSampleSize:                              /*return current sample size*/
            *((short *) infoPtr) = hwGlobals->sampleSize;
            break;

        case siSampleSizeAvailable:                     /*return sample sizes available*/
            h = NewHandle(sizeof(short) * kSampleSizesCount);
            if (h == nil)
                return (MemError());

            listPtr = (HandleListPtr) infoPtr;
            listPtr->count = 0;                         /*num. sample sizes in handle*/
            listPtr->handle = h;                        /*handle to be returned*/

            sp = (short *) *h;                          /*store sample sizes in handle*/

            for (i = 0; i < kSampleSizesCount; ++i)
                if (hwGlobals->sampleSizesActive[i])
                {
                    listPtr->count++;
                    *sp++ = hwGlobals->sampleSizes[i];
                }
            break;

        case siSampleRate:                              /*return current sample rate*/
            *((Fixed *) infoPtr) = hwGlobals->sampleRate;
            break;

        case siSampleRateAvailable:                     /*return sample rates available*/
            h = NewHandle(sizeof(UnsignedFixed) * kSampleRatesCount);
            if (h == nil)
                return (MemError());

            listPtr = (HandleListPtr) infoPtr;
            listPtr->count = 0;                         /*num. sample rates in handle*/
            listPtr->handle = h;                        /*handle to be returned*/

            lp = (UnsignedFixed *) *h;

            /*If the hardware can support a range of sample rate values,
              the list count should be set to 0 and the minimum and maximum
              sample rate values should be stored in the handle.*/
            if (hwGlobals->supportsRateRange)
            {
                *lp++ = hwGlobals->sampleRateMin;
                *lp++ = hwGlobals->sampleRateMax;
            }
            
            /*If the hardware supports a limited set of sample rates,
              the list count should be set to the number of sample rates
              and this list of rates should be stored in the handle.*/
            else
            {
                for (i = 0; i < kSampleRatesCount; ++i)
                    if (hwGlobals->sampleRatesActive[i])
                    {
                        listPtr->count++;
                        *lp++ = hwGlobals->sampleRates[i];
                    }
            }
            break;

        case siNumberChannels:                          /*return current num. channels*/
            *((short *) infoPtr) = hwGlobals->numChannels;
            break;

        case siChannelAvailable:                        /*return channels available*/
            h = NewHandle(sizeof(short) * kChannelsCount);
            if (h == nil)
                return (MemError());

            listPtr = (HandleListPtr) infoPtr;
            listPtr->count = 0;                         /*num. channels in handle*/
            listPtr->handle = h;                        /*handle to be returned*/

            sp = (short *) *h;                          /*store channels in handle*/

            for (i = 0; i < kChannelsCount; ++i)
                if (hwGlobals->channelsActive[i])
                {
                    listPtr->count++;
                    *sp++ = hwGlobals->channels[i];
                }
            break;

        case siHardwareVolume:
            *((long *)infoPtr) = hwGlobals->volume;
            break;

        /*If you do not handle a selector, delegate it up the chain.*/
        default:
            result = SoundComponentGetInfo(globals->sourceComponent, sourceID,
                                                selector, infoPtr);
            break;
    }
    return (result);
}

You can define your MySoundComponentSetInfo routine in an exactly similar fashion.


© 1998 Apple Computer, Inc.

| Previous | Chapter contents | Chapter top | Section top | Next |